import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent } from "@angular/common/http";

import { RefreshTokenService } from "../services/refreshToken.service";
import { AuthenticationService } from "../../framework/login/login.service";
import { Injectable, Injector } from "@angular/core";
import { Observable } from "rxjs/Rx";
import { mergeMap } from "rxjs/operators";
import { first } from 'rxjs/operators';

@Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
    constructor(private injector: Injector) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const tokenService = this.injector.get(RefreshTokenService);
        const authService = this.injector.get(AuthenticationService);
        if (tokenService.isAuthorized() && tokenService.tokenExpired() && !tokenService.processing && !tokenService.allowedCalls(request.url)) {
            tokenService.processing = true;
            return authService.refreshToken().pipe(mergeMap(
                (res: any) => {
                    authService.saveToken(res);
                    tokenService.publish(res);
                    tokenService.processing = false;
                    return next.handle(request);
                }
            )).catch(() => {
                tokenService.publish({});
                tokenService.processing = false;
                return next.handle(request);
            });
        } else if (tokenService.allowedCalls(request.url)) {
            return next.handle(request);
        }

        if (tokenService.processing) {
            return tokenService.storage.first().pipe(     
                mergeMap(
                () => {
                    return next.handle(request);
                }
            ));
        } else {
            return next.handle(request);
        }
    }
}